package com.cbtx.module_sp.bean;

import android.annotation.SuppressLint;
import android.app.Presentation;
import android.content.ContentResolver;
import android.content.Context;
import android.hardware.display.DisplayManager;
import android.media.AudioManager;
import android.os.Build;
import android.os.Environment;
import android.os.SystemClock;
import android.text.TextUtils;
import android.text.format.Time;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;

import com.cbtx.module_sp.utils.FileSizeUtil;
import com.cbtx.module_sp.utils.NetWorkUtil;
import com.cbtx.module_sp.utils.SimUtil;
import com.xinchao.machine.digital_advertise.tools.FileTools;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Locale;
import java.util.UUID;

/**
 * author : joker.peng
 * e-mail : joker@fiture.com
 * date   : 2021/6/10 5:38 PM
 * desc   :
 */
@SuppressLint("NewApi")
public class BaseMachine implements IMachine {

    private static final String TAG = "BaseMachine";

    private Context mContext;
    protected static final String UUID_PATH = Environment.getExternalStorageDirectory()
            .getAbsolutePath() + File.separator + ".uuid";
    private String mUuid = null;

    public BaseMachine(Context context) {
        if (context == null) {
            throw new NullPointerException("context can not be null");
        }
        mContext = context.getApplicationContext();
    }

    @Override
    public String getModel() {
        return Build.MODEL;
    } //所谓的机芯

    @Override
    public String SystemVersionName() {
        return Build.VERSION.SDK;
    }

    @Override
    public int SystemVersionCode() {
        return Build.VERSION.SDK_INT;
    }

    @Override
    public String getLocalMac() {
        String mac = getEthMac();
        if (TextUtils.isEmpty(mac)) {
            mac = getWlanMac();
            if (TextUtils.isEmpty(mac)) {
                mac = "02:00:00:00:00:00";
            }
        }
        return mac.toUpperCase();
    }

    @Override
    public String getWlanMac() {
        String filePath = "/sys/class/net/wlan0/address";
        if (FileTools.isFileExist(filePath)) {
            String wlanMac = getInfoBySuCommand("cat " + filePath);
            if (TextUtils.isEmpty(wlanMac)) {
                wlanMac = getFirstLine(filePath);
            }
            return wlanMac;
        }
        return null;
    }

    @Override
    public String getEthMac() {
        return null;
    }


    @Override
    public String getFrameworkVersion() {
        String tmp = Build.DISPLAY;
        if (!TextUtils.isEmpty(tmp) && tmp.contains("-")) {
            String[] tmps = tmp.split("-");
            tmp = tmps[0].replace("v", "").replace("V", "").trim();
        }
        return tmp;
    }

    @Override
    public long bootTime() {
        return System.currentTimeMillis() - SystemClock.elapsedRealtimeNanos() / 1000000;
    }

    @Override
    public Display[] getDisplays() {
        DisplayManager mDisplayManager = (DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE);
        return mDisplayManager.getDisplays();
    }

    @Override
    public int getDisplayCount() {
        Display[] displays = getDisplays();
        return displays == null ? 0 : displays.length;
    }

    @Override
    public int getDisplayId(Presentation presentation) {
        if (presentation == null) {
            return -1;
        }
        return presentation.getDisplay().getDisplayId();
    }

    @Override
    public boolean isMainDisplay(Presentation presentation) {
        if (presentation == null) {
            return false;
        }
        return presentation.getDisplay().getDisplayId() == 0;
    }

    @Override
    public boolean isOtherDisplay(Presentation presentation) {
        if (presentation == null) {
            return false;
        }
        return presentation.getDisplay().getDisplayId() != 0;
    }

    @Override
    public int getDisplayWidth(Display display) {
        DisplayMetrics metrics = getDisPlayMetrics(display);
        if (metrics == null) {
            return 0;
        }
        return metrics.widthPixels;
    }

    @Override
    public int getDisplayHeight(Display display) {
        DisplayMetrics metrics = getDisPlayMetrics(display);
        if (metrics == null) {
            return 0;
        }
        return metrics.heightPixels;
    }

    @Override
    public void setVolume(int vol, int type) {
        if (vol < 0 || vol > 100) {
            return;
        }
        AudioManager audioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
        int max = audioManager.getStreamMaxVolume(type);
        audioManager.setStreamVolume(type, Math.round((float) vol * max / 100), 0);
    }

    @Override
    public int setSwitchTime(int onH, int onM, int offH, int offM) {
        return 0;
    }

    @Override
    @Deprecated
    public void setSwitchStatus(boolean isOpen) {

    }

    @Override
    @Deprecated
    public void checkOnOffTime(boolean isCheck, boolean isShowToast, String toastMsg) {

    }

    @Override
    @Deprecated
    public void checkOnOffTime(boolean isCheck) {

    }

    @Override
    public void power_off() {
        executeSuCommand("reboot -p");
    }

    @Override
    public void reboot() {
        executeSuCommand("reboot");
    }

    @Override
    public long getTotalMemory() {
        String firstLine = firstLine2Number(getFirstLine("/proc/meminfo"));
        if (TextUtils.isEmpty(firstLine)) {
            return 0;
        }
        //为了方便格式化 所以乘以1024
        return Long.parseLong(firstLine) * 1024;
    }

    @Override
    public String getTotalMemory(int type) {
        switch (type) {
            case 0:
                return getTotalMemory() + "B";
            case 1:
                return getTotalMemory() / 1024 + "B";
            case 2:
                return getTotalMemory() / 1024 / 1024 + "MB";
            case 3:
                return (double) Math.round((float) getTotalMemory() / 1024 / 1024 / 1024 * 100) / 100 + "GB";
            default:
        }
        return null;
    }

    @Override
    @Deprecated
    public void setFanStatus(boolean isOn) {

    }

    @Override
    public String getSystemProperties(String key) {
        return getInfoBySuCommand("getprop " + key);
    }

    @Override
    public String setSystemProperties(String key, String value) {
        executeSuCommand("setprop " + key + " " + value);
        return getSystemProperties(key);
    }

    @Override
    @Deprecated
    public String getSerialPort() {
        return null;
    }

    @Override
    @Deprecated
    public boolean has4G() {
        return false;
    }

    @Override
    public String getName() {
        return "通用机型（" + getModel() + "）";
    }

    @Override
    public String getNameplate() {
        return "无";
    }

    @Override
    public void executeSuCommand(String cmd) {
        if (isRoot()) {
            getInfoByRunSuCmd(cmd);
        } else {
            execCommand(cmd);
        }
    }

    @Override
    public String getInfoBySuCommand(String cmd) {
        if (isRoot()) {
            return getInfoByRunSuCmd(cmd);
        } else {
            return execCommand(cmd);
        }
    }

    @Override
    @Deprecated
    public String getFanStatus() {
        return "-1";
    }

    @Override
    @Deprecated
    public int[] getCutScreen() {
        return null;
    }

    @Override
    @Deprecated
    public void startCollectWifiProbe(int collectionInterval, boolean isShowMacInLogI, WifiProbeListener listener) {

    }

    @Override
    @Deprecated
    public int enable_watchdog() {
        return 0;
    }

    @Override
    @Deprecated
    public int feed_watchdog() {
        return 0;
    }

    @Override
    @Deprecated
    public int disable_watchdog() {
        return 0;
    }

    @Override
    @Deprecated
    public void upgrade(String filePath) {

    }

    @Override
    @Deprecated
    public boolean isValidUpdateZip(String filePath) {
        return false;
    }

    @Override
    public void setSystemTime(long time) {

        Time cal = new Time();
        cal.set(time);
        String sYear = "" + cal.year;
        String sMonth;
        if (cal.month + 1 < 10) {
            sMonth = "0" + (cal.month + 1);
        } else {
            sMonth = "" + (cal.month + 1);
        }

        String sDay;
        if (cal.monthDay < 10) {
            sDay = "0" + cal.monthDay;
        } else {
            sDay = "" + cal.monthDay;
        }

        String sHour;
        if (cal.hour < 10) {
            sHour = "0" + cal.hour;
        } else {
            sHour = "" + cal.hour;
        }

        String sMin;
        if (cal.minute < 10) {
            sMin = "0" + cal.minute;
        } else {
            sMin = "" + cal.minute;
        }

        String sSec;

        if (cal.second < 10) {
            sSec = "0" + cal.second;
        } else {
            sSec = "" + cal.second;
        }

        String cmd = "date -s \"" + sYear + sMonth + sDay + "." + sHour + sMin + sSec + "\"";
        executeSuCommand(cmd);
    }

    @Override
    public String getUniqueDeviceCode() {
        if (TextUtils.isEmpty(mUuid)) {
            mUuid = getContent(UUID_PATH);
            if (TextUtils.isEmpty(mUuid)) {
                mUuid = generateUUID(Build.getSerial());
            }
        }
        return mUuid;
    }

    /**
     * 重新生成新的uuid
     *
     * @return
     */
    final private String generateUUID(String cpuSerial) {
        String board = Build.BOARD;
        String hardware = Build.HARDWARE;
        String model = getModel();
        String mac = getLocalMac();
        if (TextUtils.equals("02:00:00:00:00:00", mac)) {
            Log.d(TAG, "this machine mac is 02:00:00:00:00:00");
        }
        String mDevId = ("ck" + board + hardware + model + mac).toUpperCase();
        String uuid = new UUID(cpuSerial.hashCode(), mDevId.hashCode() << 32 | mDevId.hashCode()).toString();
        FileTools.createNewFile(UUID_PATH, uuid);
        return uuid;
    }

    @Override
    @Deprecated
    public void setLcdLightStatus(boolean isOpen) {

    }

    @Override
    @Deprecated
    public boolean getLcdLightStatus() {
        return false;
    }

    @Override
    @Deprecated
    public void setBrightness(ContentResolver resolver, int brightness) {

    }

    @Override
    @Deprecated
    public void downLTE() {

    }

    @Override
    @Deprecated
    public void upLTE() {

    }

    @Override
    @Deprecated
    public void electrify4GModel() {

    }

    @Override
    @Deprecated
    public void outage4GModel() {

    }

    @Override
    @Deprecated
    public String shotScreen(String dir, String name, int displayId) {
        return null;
    }

    @Override
    @Deprecated
    public void setMobileDataEnable(boolean enable) {

    }

    @Override
    @Deprecated
    public boolean isMobileDataEnable() {
        return false;
    }

    @Override
    public Context getContext() {
        return mContext;
    }

    @Override
    public boolean isRoot() {
        boolean root = false;

        try {
            if (!(new File("/system/bin/su")).exists() && !(new File("/system/xbin/su")).exists()) {
                root = false;
            } else {
                root = true;
            }
        } catch (Exception var2) {
            Log.d("TAG", "isRoot " + var2.getMessage());
        }

        return root;
    }

    @Override
    public String getResolutions(int screenNum) {
        Display[] displays = getDisplays();
        String resolutions = "";
        //需求方要求单屏机返回1个分辨率，其他屏幕返回系统取出来的个数
        switch (screenNum) {
            case 1:
                for (Display display : displays) {
                    if (display.getDisplayId() == 0) {
                        resolutions = getDisplayWidth(display) + "x" + getDisplayHeight(display);
                    }
                }
                break;
            default:
                for (Display display : displays) {
                    resolutions += getDisplayWidth(display) + "x" + getDisplayHeight(display) + ",";
                }
                resolutions = TextUtils.isEmpty(resolutions) ? "" : resolutions.substring(0, resolutions.length() - 1);
        }
        if (TextUtils.isEmpty(resolutions)) {
            resolutions = "1920x1080";
        }
        return resolutions;
    }

    @Override
    public String getTemperature() {
        return "";
    }

    @Override
    public String getFirstLine(String filePath) {
        try {
            FileInputStream fis = new FileInputStream(new File(filePath));
            //包装一个一行行读取的流
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fis));
            //取到所有的内存信息
            String memTotal = bufferedReader.readLine();
            return memTotal.trim();

        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    @Override
    public String firstLine2Number(String firstLine) {
        StringBuffer sb = new StringBuffer();
        for (char c : firstLine.toCharArray()) {

            if (c >= '0' && c <= '9') {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    @Override
    public String getProductType() {
        return "";
    }

    @Override
    public String getIp() {
        String ip = "";
        if (NetWorkUtil.checkEnable(getContext().getApplicationContext())) {
            ip = NetWorkUtil.getLocalIp(getContext().getApplicationContext());
        }
        return TextUtils.isEmpty(ip) ? "" : ip;
    }

    @Override
    public String getHumidity() {
        return "";
    }

    @Override
    public String getTotalExternalMemorySize() {
        return String.valueOf(FileSizeUtil.getTotalExternalMemorySize() / 1024 / 1024);
    }

    @Override
    public String getAvailableExternalMemorySize() {
        return String.valueOf(FileSizeUtil.getAvailableExternalMemorySize() / 1024 / 1024);
    }

    @SuppressLint("MissingPermission")
    @Override
    public String getIMSI() {
        String imsi = SimUtil.getSimOperator(getContext(), 0);
        return TextUtils.isEmpty(imsi) ? "" : imsi;
    }

    @Override
    public boolean setTimingSwitch(String onTime, String offTime) {
        return false;
    }

    @Override
    public void installApk(String filePath) {
        executeSuCommand("pm install -r " + filePath);
    }

    @Override
    public void clearTimingSwitch() {

    }

    @Override
    public void screenCap(int displayId, String pngFileName) {
        executeSuCommand(String.format(Locale.CHINESE, "screencap -p -d %d %s", displayId, pngFileName));
    }

    @Override
    public void screenCap(String pngFileName) {
        screenCap(0, pngFileName);
    }

    @Override
    public void updateKeepRunningFile() {

    }

    @Override
    public String getKeepRunningFile() {
        return null;
    }

    @Override
    public String getKeepBackgroundFile() {
        return null;
    }

    /**
     * 屏幕参数
     *
     * @return
     */
    @SuppressLint("NewApi")
    private DisplayMetrics getDisPlayMetrics(Display display) {
        DisplayMetrics metrics = new DisplayMetrics();
        display.getRealMetrics(metrics);
        return metrics;
    }

    /**
     * 执行系统权限命令（待验证）
     *
     * @param command
     * @return
     */
    private String execCommand(String command) {
        if (TextUtils.isEmpty(command)) {
            return "";
        }
        Process process;
        InputStream inputStream;
        BufferedReader bufferReader;
        StringBuilder results = new StringBuilder();
        try {
            process = Runtime.getRuntime().exec(command);
            inputStream = process.getInputStream();
            bufferReader = new BufferedReader(new InputStreamReader(inputStream));
            String readLine;
            while ((readLine = bufferReader.readLine()) != null) {
                results.append(readLine);
            }
            process.waitFor();
        } catch (IOException e) {
        } catch (InterruptedException e) {
        }
        return results.toString().trim();
    }

    /**
     * 执行su命令
     *
     * @param cmd
     * @return
     */
    private String getInfoByRunSuCmd(String cmd) {
        Process process = null;
        DataOutputStream os = null;
        DataInputStream is = null;
        String out = "";
        try {
            if (new File("/system/bin/su").exists()) {
                process = Runtime.getRuntime().exec("/system/bin/su");
            } else if (new File("/system/xbin/su").exists()) {
                process = Runtime.getRuntime().exec("/system/xbin/su");
            } else {
                process = Runtime.getRuntime().exec("su");
            }
            os = new DataOutputStream(process.getOutputStream());
            os.writeBytes(cmd + "\n");
            os.writeBytes("exit\n");
            os.flush();
            int aa = process.waitFor();
            is = new DataInputStream(process.getInputStream());
            byte[] buffer = new byte[is.available()];
            is.read(buffer);
            out = new String(buffer);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
                if (is != null) {
                    is.close();
                }
                process.destroy();
            } catch (Exception e) {
            }
        }
        if (TextUtils.isEmpty(out)) {
            return out;
        }
        return out.trim();
    }

    private String getContent(String file) {

        StringBuilder sb = new StringBuilder();
        if (FileTools.isFileExist(file)) {
            try {
                FileReader fileReader = new FileReader(file);
                BufferedReader buf = new BufferedReader(fileReader);
                String line = "";
                while ((line = buf.readLine()) != null) {
                    sb.append(line);
                }
                fileReader.close();
                buf.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }
}
